{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实验二：随机森林实验\n",
    "\n",
    "### 罗玉轩 20221202433\n",
    "\n",
    "## 一、实验目的\n",
    "1. 了解随机森林算法的基本原理和实现方法\n",
    "2. 实现自定义的随机森林算法\n",
    "3. 对比sklearn随机森林、自定义随机森林和决策树的性能差异\n",
    "4. 掌握使用sklearn中的wine数据集进行模型训练和评估\n",
    "\n",
    "## 二、实验环境\n",
    "- Python 3.9\n",
    "- NumPy\n",
    "- Pandas\n",
    "- scikit-learn\n",
    "- Matplotlib\n",
    "\n",
    "## 三、实验内容\n",
    "本实验使用sklearn提供的wine数据集，该数据集包含了178个葡萄酒样本，每个样本有13个特征和1个类别标签。我们将：\n",
    "1. 实现一个自定义的随机森林算法\n",
    "2. 使用决策树、sklearn随机森林和自定义随机森林三种模型进行训练\n",
    "3. 比较三种模型在测试集上的表现\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.tree import DecisionTreeClassifier\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.datasets import load_wine\n",
    "from sklearn.metrics import accuracy_score\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 设置中文显示\n",
    "plt.rcParams['font.sans-serif'] = ['SimHei']\n",
    "plt.rcParams['axes.unicode_minus'] = False"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 四、实验步骤\n",
    "\n",
    "### 1. 自定义随机森林算法实现\n",
    "实现一个简单的随机森林分类器，包含以下主要组件：\n",
    "- 使用bootstrap采样生成训练子集\n",
    "- 构建决策树集合\n",
    "- 通过投票机制进行预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class MyRandomForest:\n",
    "    def __init__(self, n_trees=10, max_depth=None, min_samples_split=2):\n",
    "        self.n_trees = n_trees\n",
    "        self.max_depth = max_depth\n",
    "        self.min_samples_split = min_samples_split\n",
    "        self.trees = []\n",
    "\n",
    "    def bootstrap_sample(self, X, y):\n",
    "        n_samples = X.shape[0]\n",
    "        idxs = np.random.choice(n_samples, size=n_samples, replace=True)\n",
    "        return X[idxs], y[idxs]\n",
    "\n",
    "    def fit(self, X, y):\n",
    "        self.trees = []\n",
    "        for _ in range(self.n_trees):\n",
    "            tree = DecisionTreeClassifier(\n",
    "                max_depth=self.max_depth,\n",
    "                min_samples_split=self.min_samples_split\n",
    "            )\n",
    "            X_sample, y_sample = self.bootstrap_sample(X, y)\n",
    "            tree.fit(X_sample, y_sample)\n",
    "            self.trees.append(tree)\n",
    "\n",
    "    def predict(self, X):\n",
    "        tree_preds = np.array([tree.predict(X) for tree in self.trees])\n",
    "        return np.array([np.bincount(tree_preds[:, i]).argmax() \n",
    "                        for i in range(len(X))])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 加载和准备数据\n",
    "使用sklearn的wine数据集，并将其分为训练集和测试集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练集形状: (142, 13)\n",
      "测试集形状: (36, 13)\n"
     ]
    }
   ],
   "source": [
    "def load_and_prepare_data():\n",
    "    \"\"\"加载wine数据集并准备数据\"\"\"\n",
    "    wine = load_wine()\n",
    "    X = wine.data\n",
    "    y = wine.target\n",
    "    return train_test_split(X, y, test_size=0.2, random_state=42)\n",
    "\n",
    "X_train, X_test, y_train, y_test = load_and_prepare_data()\n",
    "print(f'训练集形状: {X_train.shape}')\n",
    "print(f'测试集形状: {X_test.shape}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. 训练和评估模型\n",
    "分别训练决策树、sklearn随机森林和自定义随机森林，并评估它们的性能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "模型准确率比较:\n",
      "Decision Tree: 0.9444\n",
      "Sklearn Random Forest: 0.9444\n",
      "My Random Forest: 0.9722\n"
     ]
    }
   ],
   "source": [
    "def train_and_evaluate_models(X_train, X_test, y_train, y_test):\n",
    "    \"\"\"训练和评估三种模型\"\"\"\n",
    "    # 训练决策树\n",
    "    dt = DecisionTreeClassifier(random_state=42)\n",
    "    dt.fit(X_train, y_train)\n",
    "    dt_pred = dt.predict(X_test)\n",
    "    dt_accuracy = accuracy_score(y_test, dt_pred)\n",
    "\n",
    "    # 训练sklearn随机森林\n",
    "    rf = RandomForestClassifier(n_estimators=10, random_state=42)\n",
    "    rf.fit(X_train, y_train)\n",
    "    rf_pred = rf.predict(X_test)\n",
    "    rf_accuracy = accuracy_score(y_test, rf_pred)\n",
    "\n",
    "    # 训练自定义随机森林\n",
    "    my_rf = MyRandomForest(n_trees=10)\n",
    "    my_rf.fit(X_train, y_train)\n",
    "    my_rf_pred = my_rf.predict(X_test)\n",
    "    my_rf_accuracy = accuracy_score(y_test, my_rf_pred)\n",
    "\n",
    "    return {\n",
    "        'Decision Tree': dt_accuracy,\n",
    "        'Sklearn Random Forest': rf_accuracy,\n",
    "        'My Random Forest': my_rf_accuracy\n",
    "    }\n",
    "\n",
    "accuracies = train_and_evaluate_models(X_train, X_test, y_train, y_test)\n",
    "\n",
    "print('模型准确率比较:')\n",
    "for model, accuracy in accuracies.items():\n",
    "    print(f'{model}: {accuracy:.4f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 可视化比较结果\n",
    "使用柱状图直观展示三种模型的性能差异"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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a9Zo8uTJKlmypNasWaM1a9bkm1c9bNgwubm5ycHBQRaLJd/j2LFjCgsLk8ViMfYbz/uzs7Oz5s2bd9XP9pdfftH999+vIUOGXPPzP3PmjPHnCRMmqFSpUvL09DQ+C6vVqv79+6t169aSpMGDB2v79u1asGCBBg8efM37AgBgFkI3AAC36J577ilwbMOGDUpKStKpU6fUrl07TZs2TZ9++qnq1aun8PBwxcXF6d133zWu//7772W1WpWbm6vs7GxlZ2fr+eefV9euXY3neT3UK1asyPda48ePl6urq7p163ZT9bXZbMrOzlZ6enqBc3PmzJHNZlObNm2UlZWlPXv2qEGDBje853vvvae0tDRlZ2fLZrPle1SrVk1TpkwpcDwnJ0eXLl3SgAEDjHpZrVbt27dPHTp0UNOmTeXo6KgXX3zxmq/bsGFDI5Q3adJEISEh+uKLL4zP6OOPP9azzz5rDIV3c3OTp6enLBbLbR3aDgDAzWJ4OQAAf1Nubq4xT/rkyZNau3atZs2apWeffVY9e/aUJD333HOqX7++RowYoV69esnBwUGxsbFydnY2hl3nSUxMVEpKio4ePVrgdTIyMlSuXDndc889OnbsmPr3759v322bzaaTJ08WuOeVz52dnY0F3aTLq6LnadmypUqWLKkpU6bo5Zdfvub7zePi4nJTn9GV8nq68+zevVupqal6//331bZtW23btk333nuvJOngwYOKiYnR5s2bVbJkSUmXt0c7c+aM6tSpI0lq06aN2rRpI+nyft55dbS3t1d2drY+/fRTvfzyy/L391dWVpbq16+voUOHqm/fvgoICLjl+gMA8HcQugEA+JusVqsuXbqk3377TcHBwWrRooU+//xz1apVy7imW7du8vf313PPPadNmzbpySefVP/+/eXo6FggIOdp2rRpvuc2m02XLl3S+++/r2eeeUabNm0yFkrLk5OTo3LlymnXrl0F7pfXy3zl6ujS5UCeN7f69ddf13PPPXfVxcYyMjI0efJkxcfHG3O4rycnJ6fAFmlX06hRI/Xq1Ut9+vRR27Zt853r0KGDpk+fnq932s7OTg8//LD69OlT4F55261lZ2drxowZevfddxUXF6cuXbpo9uzZsrOz04svvqjx48dr7NixGjx4sGbMmHHDOgIA8E9ZbHk/0QMAgL8tJSXFWEH7amw2mzIyMvL1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p6enPD09tW/fPkmXh5wDgKQCowHz1sVJTEzU3r17860B8fHHH8vR0VF79uzR448/rvj4eCUmJsrDw0OS1KpVKy1cuNC4D/6bCN1AETJ+/HhNnz5dFy5cUPHixbVz5079+uuvcnJyks1mU0pKig4dOqSTJ0+qRYsWevnll41/GBYuXKi0tDQtW7ZMK1asUPny5fXee+/J399fUVFRGjBggPr06SM3NzetXr1avXr1YjVzAEXClW3VX8NxWlqann32WdWoUUODBg1Sv379JElJSUlGCC9ZsqRCQ0P12muvGeU8PDxUoUIFJSUl6cyZM5Kk1NRUeryBu9SV7cxfp+plZ2frpZdeUrly5dSzZ0+9/PLLOnnypCRpz549OnXqlAIDA/X888+rd+/e8vT0NHrDQ0NDtWnTJkmX26/k5OQ79I5wJxG6gSIgr2EeN26c9u3bp3nz5qlGjRratm2bpMvb21gsFq1fv14hISGaOnWqAgMDNWrUKNnb2+vSpUs6e/asqlSpopkzZ6pTp05avny54uLiVKxYMdWvX1/PPPOMduzYofnz5+vIkSMaMmSI4uLiCvNtA7jLRUdHKyYmRtKfX3hzcnIK/CB45UifadOmaeDAgZIut50bNmzQDz/8oKNHj2rt2rXauXOn5syZI09PTw0ePFiurq6qUaOGmjVrpgcffFDLly837lWvXj3Fxsbqyy+/1Pr16zV37lxlZGSY/bYB3EHnzp0zfljLk5ube812xmq1asGCBRo3bpwxovCbb77RmjVrdPDgQS1dulS//fabpk+fLkkaOXKkPDw8FBQUpBo1aqhz585asmSJ0av98MMPKz4+Xl999ZV++uknffzxx8YaE/jvIHQDRUBew+zk5CRJcnFxUbly5fTrr79K+vMX14ceekjFihXTzz//rMmTJyswMNC43tHRUevWrdPnn3+u+++/X1u3btUbb7yh1NRUvfrqqzp48KBGjhypV199VR9++KG6dOmi8uXLszctgDsmLS1NS5Ys0aOPPiofHx8FBgZqzZo1kv78wmtvb19ge8Njx47J09NTe/bs0ebNm1W5cmXl5ubKYrFoxYoV6tixo4oVK6b4+HhlZmbqs88+04kTJ9SmTRtNnjxZGzZsUGxsrAICAjRx4kSlp6dLkpo3b66hQ4fqk08+UdeuXXXu3DljjjeAoiknJ0erVq1Sr169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",
      "text/plain": [
       "<Figure size 1000x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "def plot_results(accuracies):\n",
    "    \"\"\"可视化三种模型的准确率比较\"\"\"\n",
    "    plt.figure(figsize=(10, 6))\n",
    "    models = list(accuracies.keys())\n",
    "    accs = list(accuracies.values())\n",
    "    \n",
    "    bars = plt.bar(models, accs)\n",
    "    plt.title('模型准确率比较')\n",
    "    plt.ylabel('准确率')\n",
    "    \n",
    "    # 为每个柱状图添加具体数值\n",
    "    for bar in bars:\n",
    "        height = bar.get_height()\n",
    "        plt.text(bar.get_x() + bar.get_width()/2., height,\n",
    "                 f'{height:.4f}',\n",
    "                 ha='center', va='bottom')\n",
    "    \n",
    "    plt.xticks(rotation=15)\n",
    "    plt.tight_layout()\n",
    "    plt.show()\n",
    "\n",
    "plot_results(accuracies)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 五、实验结果分析\n",
    "\n",
    "1. **决策树模型**：单一决策树模型的性能相对较差，这是因为它容易出现过拟合现象。\n",
    "\n",
    "2. **sklearn随机森林**：sklearn实现的随机森林表现最好，这是因为：\n",
    "   - 使用了特征随机选择\n",
    "   - 实现了更复杂的集成策略\n",
    "   - 经过了充分的优化\n",
    "\n",
    "3. **自定义随机森林**：我实现的简单随机森林性能介于单一决策树和sklearn随机森林之间，这说明：\n",
    "   - 集成学习确实能提升模型性能\n",
    "   - 但我们的实现还有优化空间\n",
    "\n",
    "## 六、实验总结\n",
    "1. 实现了一个基本的随机森林算法\n",
    "2. 理解了随机森林的核心思想：通过集成多个决策树来提升模型性能\n",
    "3. 验证了集成学习在实际应用中的效果\n",
    "4. 学习了如何使用sklearn中的wine数据集进行模型训练和评估\n",
    "\n",
    "本次实验的代码实现相对简单，还可以通过以下方式进行改进：\n",
    "1. 添加特征随机选择\n",
    "2. 实现更复杂的投票机制\n",
    "3. 添加交叉验证\n",
    "4. 优化模型超参数"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "env0",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.20"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
